package gz.metro.datasync.utils;

import gz.metro.datasync.utils.enums.Status;
import org.springframework.http.HttpHeaders;

import java.io.Serializable;

public class ApiResponse<T> implements Serializable {
    public static final ApiResponse OK;
    public static final ApiResponse ACCEPTED;
    public static final ApiResponse NO_CONTENT;
    public static final ApiResponse NOT_FOUND;
    public static final ApiResponse NOT_IMPLEMENTED;
    public Status status;
    public Object entity;
    public HttpHeaders headers = new HttpHeaders();

    public static <T> ApiResponse<T> ok(T entity) {
        return of(Status.OK, entity);
    }

    public static <T> ApiResponse<T> created(T entity) {
        return of(Status.CREATED, entity);
    }

    public static ApiResponse badRequest(String message) {
        return err(Status.BAD_REQUEST, message);
    }

    public static <T> ApiResponse<T> notFound(String message) {
        return err(Status.NOT_FOUND, message);
    }

    public static ApiResponse err(Status status, String message) {
        return new ApiResponse(status, message);
    }

    public static <T> ApiResponse<T> of(Status status, T entity) {
        return new ApiResponse(status, entity);
    }

    public static <T> ApiResponse<T> of(T entity) {
        return null == entity ? NOT_FOUND : ok(entity);
    }

    protected ApiResponse(Status status, Object entity) {
        this.status = status;
        this.entity = entity;
    }

    public Status getStatus() {
        return this.status;
    }

    public HttpHeaders getHeaders() {
        return this.headers;
    }

    public Object getEntity() {
        return this.entity;
    }

    public ApiResponse setHeader(String name, String value) {
        this.headers.set(name, value);
        return this;
    }

    public ApiResponse addHeader(String name, String value) {
        this.headers.add(name, value);
        return this;
    }

    static {
        OK = of(Status.OK, (Object) null);
        ACCEPTED = of(Status.ACCEPTED, (Object) null);
        NO_CONTENT = of(Status.NO_CONTENT, (Object) null);
        NOT_FOUND = err(Status.NOT_FOUND, "The resource does not exists.");
        NOT_IMPLEMENTED = err(Status.NOT_IMPLEMENTED, "Not implemented operation.");
    }
}